package com.clearliang.netmodule;

import android.os.Environment;
import android.util.Log;

import com.clearliang.netmodule.api.ApiService;
import com.clearliang.netmodule.api.AppClient;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;

/**
 * Created by ClearLiang on 2019/5/18
 * <p>
 * Function : 网络
 */
public class NetUtil {
    private static OkHttpClient okHttpClient;
    private static ApiService apiStores;

    private static NetUtil instance;

    private NetUtil() {
    }

    public static NetUtil getCookieUtil() {
        if (instance == null) {
            synchronized (NetUtil.class) {
                if (instance == null) {
                    okHttpClient = new OkHttpClient.Builder()
                            .connectTimeout(15, TimeUnit.SECONDS) //设置超时
                            .readTimeout(20, TimeUnit.SECONDS)
                            .writeTimeout(20, TimeUnit.SECONDS)
                            .retryOnConnectionFailure(true)
                            .build();//错误重连
                    apiStores = AppClient.retrofit().create(ApiService.class);
                    instance = new NetUtil();
                }
            }
        }
        return instance;
    }

    /**
     * 异步GET请求
     *
     * @param url
     * @param callback
     */
    public void get(String url, Callback callback) {
        final Request request = new Request.Builder()
                .url(url)
                .get()//默认就是GET请求，可以不写
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
        /*
            call.enqueue(new Callback() {
                //请求失败执行的方法
                @Override
                public void onFailure(Call call, IOException e) {
                }
                //请求成功执行的方法
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                }
            });
         */
    }

    /**
     * 同步GET请求
     *
     * @param url
     * @return
     */
    public Response[] get(String url) {
        final Response[] response = new Response[1];
        final Request request = new Request.Builder()
                .url(url)
                .build();
        final Call call = okHttpClient.newCall(request);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    response[0] = call.execute();
                    showLog("run: " + response[0].body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        return response;
    }

    /**
     * 异步POST请求提交字符串
     *
     * @param url
     */
    public void post(String url, Map map, Callback callback) {
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");//"类型,字节码"

        StringBuilder stringBuffer = new StringBuilder();
        Set<Map.Entry<String, String>> set = map.entrySet();
        Iterator<Map.Entry<String, String>> iterator = set.iterator();

        stringBuffer.append("{");
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            stringBuffer.append(entry.getKey());
            stringBuffer.append(":");
            stringBuffer.append(entry.getValue());
            stringBuffer.append(";");
        }
        stringBuffer.replace(stringBuffer.length() - 1, stringBuffer.length(), "}");
        //String value = "{username:admin;password:admin}";
        //1.创建OkHttpClient对象
        //okHttpClient = new OkHttpClient();
        //2.通过RequestBody.create 创建requestBody对象
        RequestBody requestBody = RequestBody.create(mediaType, stringBuffer.toString());
        //3.创建Request对象，设置URL地址，将RequestBody作为post方法的参数传入
        Request request = new Request.Builder().url(url).post(requestBody).build();
        //4.创建一个call对象,参数就是Request请求对象
        Call call = okHttpClient.newCall(request);
        //5.请求加入调度,重写回调方法
        call.enqueue(callback);
    }

    public void post(String url, String json, Callback callback) {
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");//"类型,字节码"
        //String value = "{username:admin;password:admin}";
        //1.创建OkHttpClient对象
        //okHttpClient = new OkHttpClient();
        //2.通过RequestBody.create 创建requestBody对象
        RequestBody requestBody = FormBody.create(mediaType, json);
        //3.创建Request对象，设置URL地址，将RequestBody作为post方法的参数传入
        Request request = new Request.Builder().url(url).post(requestBody).build();
        //4.创建一个call对象,参数就是Request请求对象
        Call call = okHttpClient.newCall(request);
        //5.请求加入调度,重写回调方法
        call.enqueue(callback);
    }

    /**
     * 异步POST请求上传文件
     *
     * @param url
     * @param childName
     * @param callback
     */
    public void postFile(String url, String childName, Callback callback) {
        //1.创建OkHttpClient对象
        //上传的图片
        File file = new File(Environment.getExternalStorageDirectory(), childName);//"zhuangqilu.png"
        //2.通过RequestBody.create 创建requestBody对象,application/octet-stream 表示文件是任意二进制数据流
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        //3.创建Request对象，设置URL地址，将RequestBody作为post方法的参数传入
        Request request = new Request.Builder().url(url).post(requestBody).build();
        //4.创建一个call对象,参数就是Request请求对象
        Call call = okHttpClient.newCall(request);
        //5.请求加入调度,重写回调方法
        call.enqueue(callback);
    }

    /**
     * 参数的post请求
     *
     * @param url
     * @param map
     * @param callback
     */
    public void postForm(String url, Map map, Callback callback) {
        //字符串
        Set<Map.Entry<String, String>> set = map.entrySet();
        Iterator<Map.Entry<String, String>> iterator = set.iterator();

        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            bodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
        }
        RequestBody requestBody = bodyBuilder.build();
        /*RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("username", "叶应是叶")
                .addFormDataPart("password", "叶应是叶")
                .build();*/
        final Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);
    }

    /**
     * 实现模块化，独立网络请求
     *
     * @param subscriber
     */
    public void test(final Subscriber subscriber) {
        addSubscription(apiStores.getMovies(), new Subscriber<ResponseBody>() {
            @Override
            public void onCompleted() {
                onUnsubscribe();
                showLog("父——完成");
                subscriber.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                onUnsubscribe();
                showLog("父——错误");
                subscriber.onError(e);
            }

            @Override
            public void onNext(ResponseBody responseBody) {
                subscriber.onNext(responseBody);
            }
        });
    }

    private CompositeSubscription mCompositeSubscription;

    //在程序结束的时候注销
    public void onUnsubscribe() {
        if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) {
            mCompositeSubscription.unsubscribe();
            mCompositeSubscription = null;
        }
    }

    public <T> void addSubscription(Observable<T> observable, Subscriber<T> subscriber) {
        if (mCompositeSubscription == null) {
            mCompositeSubscription = new CompositeSubscription();
        }
        mCompositeSubscription.add(observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber));
    }


    private void showLog(String msg) {
        Log.e("信息", msg);
    }
}
